package com.robbykrlos.androbert;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.util.Log;
import android.util.Pair;
import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TableRow;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

/**
 * Created by RobbyKrlos on 06.12.2014.
 */
public class GamePlan {
    private Integer intHeight=25;
    private Integer intWidth=25;

    private Integer intGamePoints=0;
    private Integer intPointsCounter=0;
    private Integer intMaxBytes=0;

    private RoBert roBert = new RoBert();

    private Pair<Integer,Integer> pairStartPos = new Pair<Integer, Integer>(0,0);
    private ArrayList <GameObstacle> arrGameObstacles = new ArrayList<GameObstacle>();

    private MainActivity mainActivity;

    public GamePlan () {
        this.setIntHeight(25);
        this.setIntWidth(25);
        this.setPairStartPos(new Pair<Integer, Integer>(this.getIntWidth()/2+1, this.getIntHeight()/2+1));

//        this.populateGamePlanWithObstacles(10);
        this.roBert.setPairCurrentPos(this.getPairStartPos());
    }

    public GamePlan (Integer intHeight, Integer intWidth) {
        this.intHeight = intHeight;
        this.intWidth = intWidth;
        this.pairStartPos = new Pair<Integer, Integer>(4,4);

//        this.populateGamePlanWithObstacles(10);
        this.roBert.setPairCurrentPos(this.getPairStartPos());
    }

    public GamePlan (Integer intHeight, Integer intWidth, Pair pairStartPos) {
        this.intHeight = intHeight;
        this.intWidth = intWidth;
        this.pairStartPos = pairStartPos;

//        this.populateGamePlanWithObstacles(10);
        this.roBert.setPairCurrentPos(this.getPairStartPos());
    }

    public void setMainActivity(MainActivity mainActivity) {
        this.mainActivity = mainActivity;
    }
    public MainActivity getMainActivity() {
        return mainActivity;
    }
    public void sendMainActivityConsoleMessage(String strMessage){
        this.mainActivity.write2Console(strMessage);
    }

    public ArrayList<GameObstacle> getArrGameObstacles() {
        return arrGameObstacles;
    }
    public void setArrGameObstacles(ArrayList<GameObstacle> arrGameObstacles) { this.arrGameObstacles = arrGameObstacles; }
    public void addGameObstacle2Arr(GameObstacle objGameObstacle) {
        this.arrGameObstacles.add(objGameObstacle);
    }

    public Integer getIntHeight() {
        return intHeight;
    }
    public void setIntHeight(Integer intHeight) {
        this.intHeight = intHeight;
    }

    public Integer getIntWidth() {
        return intWidth;
    }
    public void setIntWidth(Integer intWidth) {
        this.intWidth = intWidth;
    }

    public void setIntGamePoints(Integer intGamePoints) {
        this.intGamePoints = intGamePoints;
    }
    public Integer getIntGamePoints() {
        return intGamePoints;
    }

    public void setIntMaxBytes(Integer intMaxBytes) {
        this.intMaxBytes = intMaxBytes;
    }
    public Integer getIntMaxBytes() {
        return intMaxBytes;
    }

    public void setIntPointsCounter(Integer intPointsCounter) {
        this.intPointsCounter = intPointsCounter;
    }
    public Integer getIntPointsCounter() {
        return intPointsCounter;
    }
    public void incrementPointCounter(){
        this.intPointsCounter++;
    }
    public void decrementPointCounter(){
        this.intPointsCounter--;
    }

    public void setRoBert(RoBert roBert) {
        this.roBert = roBert;
    }
    public RoBert getRoBert() {
        return roBert;
    }

    public void setPairStartPos(Pair<Integer, Integer> pairStartPos) {this.pairStartPos = pairStartPos; }
    public Pair<Integer, Integer> getPairStartPos() {return pairStartPos; }


    public byte getObstacleTypeForPair(Pair <Integer,Integer> pair) {

//        Log.w("Debug:", pair.first + " | " + pair.second);

        ArrayList<GameObstacle> arrGameObstaclesTemp = this.getArrGameObstacles();

        for(int intIndexPair = 0; intIndexPair < this.arrGameObstacles.size(); intIndexPair++){

            GameObstacle gameObstacle = arrGameObstaclesTemp.get(intIndexPair);

//            Log.w("XXX", gameObstacle.getPairObstaclePos().first.toString() +
//                    " | " + gameObstacle.getPairObstaclePos().second.toString() +
//                    " : " + Byte.valueOf(gameObstacle.getObstacleType()).toString() );

            if(gameObstacle.getPairObstaclePos().first == pair.first &&
                    gameObstacle.getPairObstaclePos().second == pair.second){
                //Log.w("1", Byte.valueOf(this.arrGameObstacles.get(intIndexPair).getObstacleType()).toString());
                return gameObstacle.getObstacleType();
            }
        }
        //Log.w("0", Byte.valueOf(GameObstacle.ObstacleTypes.NONE).toString());
        return GameObstacle.ObstacleTypes.NONE;
    }

    public boolean isPairRoBert(Pair <Integer,Integer> pair) {
        return (this.roBert.getPairCurrentPos().first == pair.first && this.roBert.getPairCurrentPos().second == pair.second);
    }

    public void polulateGamePlanWithObstacles(Integer intNrObstacles){
        for(int intIndex = 1; intIndex <= intNrObstacles; intIndex++){
            GameObstacle gameObstacle = GameObstacle.generateObstacle(this.getIntWidth());
            if(gameObstacle.getPairObstaclePos().first != this.pairStartPos.first ||
                    gameObstacle.getPairObstaclePos().second != this.pairStartPos.second){
                this.addGameObstacle2Arr(gameObstacle);
            }
        }
    }

    public void displayGamePlan2TableLayout(TableLayout tableLayout){
        //clear all before re-run
        tableLayout.removeAllViews();

        for(int intIndexRows = 0; intIndexRows < this.intHeight ; intIndexRows++){
            TableRow tableRow = new TableRow(tableLayout.getContext());
            tableLayout.addView(tableRow);
            for(int intIndexCols = 0; intIndexCols < this.intWidth ; intIndexCols++){

//                Log.w("Tag", ((Integer) intIndexRows).toString() + "-" + ((Integer) intIndexCols).toString()  + "\r\n");

                //TODO : BUG HERE : 24/24 always.
                Pair pairCurrentTableCell = new Pair<Integer, Integer>(intIndexRows, intIndexCols);

                Paint paint = new Paint();
                Bitmap bitmap = Bitmap.createBitmap(14, 14, Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(bitmap);

                if(this.isPairRoBert(pairCurrentTableCell)) {
                    paint.setColor(Color.GREEN);
                    canvas.drawRect(2, 2, 12, 12, paint);
                }

                byte byteCurrentObstacleType = this.getObstacleTypeForPair(pairCurrentTableCell);

//                Log.w("Debug:",(Byte.valueOf(byteCurrentObstacleType).toString()) + " : " + pairCurrentTableCell.first + " | " + pairCurrentTableCell.second);

                switch (byteCurrentObstacleType){
                    case GameObstacle.ObstacleTypes.NONE:
                        paint.setColor(Color.BLACK);
                        canvas.drawRect(6, 6, 8, 8, paint);
                        break;

                    case GameObstacle.ObstacleTypes.PENALTY:
                        paint.setColor(Color.RED);
                        canvas.drawCircle(7, 7, 4, paint);
                        break;

                    case GameObstacle.ObstacleTypes.POINT:
                        paint.setColor(Color.BLUE);
                        canvas.drawCircle(7, 7, 4, paint);
                        break;

                    default:
                        paint.setColor(Color.BLACK);
                        canvas.drawRect(2, 2, 12, 12, paint);
                        break;
                }

                RelativeLayout relativeLayout = new RelativeLayout(tableLayout.getContext());
                relativeLayout.setBackground(new BitmapDrawable(tableLayout.getResources(), bitmap));
                tableRow.addView(relativeLayout);
            }
        }
    }

    public void loadGamePlanFromFile(String strGamePlanName){
        try {
            InputStream inputStream = this.mainActivity.getResources().openRawResource(R.raw.level1);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String strCurrentLine;

            for (int y = 0; y < this.getIntHeight(); y++) {
                strCurrentLine = bufferedReader.readLine();
//                Log.w("Debug",strCurrentLine);

                for (int x = 0; x < this.getIntWidth(); x++) {
                    GameObstacle objCurrentObstacle = new GameObstacle();
                    objCurrentObstacle.setPairObstaclePos(new Pair<Integer, Integer>(x, y));

//                    Log.w("Char:", String.valueOf(strCurrentLine.charAt(x)));

                    switch (strCurrentLine.charAt(x)) {
                        case GameObstacle.ObstacleCodes.NONE:
//                            Log.w("Case:", "NONE");
                            objCurrentObstacle.setObstacleType(GameObstacle.ObstacleTypes.NONE);
                            break;

                        case GameObstacle.ObstacleCodes.PENALTY:
//                            Log.w("Case:", "PENALTY");
                            objCurrentObstacle.setObstacleType(GameObstacle.ObstacleTypes.PENALTY);
                            break;

                        case GameObstacle.ObstacleCodes.POINT:
//                            Log.w("Case:", "POINT");
                            objCurrentObstacle.setObstacleType(GameObstacle.ObstacleTypes.POINT);
                            this.incrementPointCounter();
                            break;

                        case GameObstacle.ObstacleCodes.WALL_X:
                            objCurrentObstacle.setObstacleType((byte) (GameObstacle.ObstacleTypes.WALL_W | GameObstacle.ObstacleTypes.WALL_E | GameObstacle.ObstacleTypes.WALL_N | GameObstacle.ObstacleTypes.WALL_S));
                            break;

                        case GameObstacle.ObstacleCodes.WALL_W:
                            objCurrentObstacle.setObstacleType(GameObstacle.ObstacleTypes.WALL_W);
                            break;

                        case GameObstacle.ObstacleCodes.WALL_E:
                            objCurrentObstacle.setObstacleType(GameObstacle.ObstacleTypes.WALL_E);
                            break;

                        case GameObstacle.ObstacleCodes.WALL_N:
                            objCurrentObstacle.setObstacleType(GameObstacle.ObstacleTypes.WALL_N);
                            break;

                        case GameObstacle.ObstacleCodes.WALL_S:
                            objCurrentObstacle.setObstacleType(GameObstacle.ObstacleTypes.WALL_S);
                            break;

                        case GameObstacle.ObstacleCodes.WALL_EW:
                            objCurrentObstacle.setObstacleType((byte) (GameObstacle.ObstacleTypes.WALL_W | GameObstacle.ObstacleTypes.WALL_W));
                            break;

                        case GameObstacle.ObstacleCodes.WALL_NS:
                            objCurrentObstacle.setObstacleType((byte) (GameObstacle.ObstacleTypes.WALL_N | GameObstacle.ObstacleTypes.WALL_S));
                            break;

                        case GameObstacle.ObstacleCodes.WALL_NW:
                            objCurrentObstacle.setObstacleType((byte) (GameObstacle.ObstacleTypes.WALL_W | GameObstacle.ObstacleTypes.WALL_N));
                            break;

                        case GameObstacle.ObstacleCodes.WALL_SW:
                            objCurrentObstacle.setObstacleType((byte) (GameObstacle.ObstacleTypes.WALL_W | GameObstacle.ObstacleTypes.WALL_S));
                            break;

                        case GameObstacle.ObstacleCodes.WALL_NE:
                            objCurrentObstacle.setObstacleType((byte) (GameObstacle.ObstacleTypes.WALL_E | GameObstacle.ObstacleTypes.WALL_N));
                            break;

                        case GameObstacle.ObstacleCodes.WALL_ES:
                            objCurrentObstacle.setObstacleType((byte) (GameObstacle.ObstacleTypes.WALL_E | GameObstacle.ObstacleTypes.WALL_S));
                            break;

                        case GameObstacle.ObstacleCodes.WALL_WNE:
                            objCurrentObstacle.setObstacleType((byte) (GameObstacle.ObstacleTypes.WALL_W | GameObstacle.ObstacleTypes.WALL_E | GameObstacle.ObstacleTypes.WALL_N));
                            break;

                        case GameObstacle.ObstacleCodes.WALL_ESW:
                            objCurrentObstacle.setObstacleType((byte) (GameObstacle.ObstacleTypes.WALL_W | GameObstacle.ObstacleTypes.WALL_E | GameObstacle.ObstacleTypes.WALL_S));
                            break;

                        case GameObstacle.ObstacleCodes.WALL_SWN:
                            objCurrentObstacle.setObstacleType((byte) (GameObstacle.ObstacleTypes.WALL_W | GameObstacle.ObstacleTypes.WALL_N | GameObstacle.ObstacleTypes.WALL_S));
                            break;

                        case GameObstacle.ObstacleCodes.WALL_NES:
                            objCurrentObstacle.setObstacleType((byte) (GameObstacle.ObstacleTypes.WALL_E | GameObstacle.ObstacleTypes.WALL_N | GameObstacle.ObstacleTypes.WALL_S));
                            break;

                        case GameObstacle.ObstacleCodes.START:
                            this.setPairStartPos(new Pair<Integer, Integer>(x, y));
                            this.roBert.setPairCurrentPos(new Pair<Integer, Integer>(x, y));
                            break;
                    }

//                    Log.w("0", Byte.valueOf(objCurrentObstacle.getObstacleType()).toString());
                    this.addGameObstacle2Arr(objCurrentObstacle);
//                    Log.w("OBJ", Byte.valueOf(this.getArrGameObstacles().get(this.getArrGameObstacles().size()-1).getObstacleType()).toString());
                }
            }
        }catch(Exception ex){
//            Log.e("PlanLoadError", ex.getMessage().toString() + ex.getStackTrace().toString());
            this.mainActivity.write2Console(ex.getMessage().toString() + ex.getStackTrace().toString());
        }

    }
}
